package engine.Astar
{
	import flash.geom.Point;

	/**
	 *
	 * @author zane
	 */
	public class AcorrsLineGrid
	{
		private var nodes:Array;
		private var nodeWidth:Number;
		private var nodeHeight:Number;
		private var arrange:Arrange;

		//---直线方程系数
		private var _k:Number;
		private var _b:Number;
		private var _isPanX:Boolean=false;
		private var _panXvalue:int;
		private var _isPanY:Boolean=false;
		private var _panYvalue:int;

		private var _mapsGrid:MapGrid;
		private var _astartNodes:Array;

		/**
		 *
		 * @param maps
		 * @param ns
		 */
		public function AcorrsLineGrid(maps:MapGrid, ns:Array=null)
		{
			this._mapsGrid=maps;

			this._astartNodes=ns;
			nodeWidth=30;
			nodeHeight=15;
			arrange=new Arrange();
			arrange.key="f";
		}

		/**
		 *
		 * @param arr
		 * @return
		 * @throws Error
		 */
		public function getPsnode(arr:Array=null):Array
		{
			//trace("asdf")
			//trace("------------------------------------ getPsnode");


			if (arr == null)
				arr=_astartNodes;
			if (arr == null || _mapsGrid == null)
				throw new Error("没有合适节点可供计算：in AcorrsLineGrid");

			var len:uint=arr.length;
			if (len < 3)
				return arr;

			var psArr:Array=[];
			var node:Node=arr[0] as Node;

			var endNode:Node=arr[len - 1] as Node;

			var index:uint=0;
			psArr.push(node);

			while (node != endNode)
			{

				for (var i:int=len - 1; i > index; i--)
				{
					var test:Node=arr[i] as Node;
					var neigbor:Boolean=Boolean((i - index) == 1);
					if (neigbor || isCorrsed(node, test))
					{
						//trace("Node " + i+"  "+(neigbor));
						node=test;
						index=i;
						psArr.push(test);
						break;
					}
				}
			}

			return psArr;
		}




		private function isCorrsed(s:Node, e:Node):Boolean
		{

			if (!s || !e)
				return false;
			_isPanX=s.y == e.y;
			_isPanY=s.x == e.x;

			if (_isPanX || _isPanY)
			{
				if (_isPanX)
					_panXvalue=s.y * nodeHeight;
				if (_isPanY)
					_panYvalue=s.x * nodeWidth;
			}
			else
			{
				_k=((e.y - s.y) * nodeHeight) / ((e.x - s.x) * nodeWidth);
				_b=(e.y + 0.5) * nodeHeight - (((e.x + 0.5) * nodeWidth) * _k);
			}


			var minx:int=Math.min(e.x, s.x);
			var maxx:int=Math.max(e.x, s.x);
			var miny:int=Math.min(s.y, e.y);
			var maxy:int=Math.max(s.y, e.y);

			var startPx:int=(minx + 0.5) * nodeWidth;
			var endPx:int=(maxx + 0.5) * nodeWidth;
			var startPy:int=(miny + 0.5) * nodeHeight;
			var endPy:int=(maxy + 0.5) * nodeHeight;
			var node:Node;

			//x轴采样:
			var px:int;
			var py:int;
			var acnode:Node;
			node=s.x < e.x ? s : e;
			var i:int;
			for (i=minx; i <= maxx; i++)
			{
				px=i * nodeWidth + 1;
				if (px >= startPx && px <= endPx)
				{
					py=getPy(px);
					//trace("x1 " + px + " " + py);
					acnode=_mapsGrid.getNodeByPoint(new Point(px, py));
					if (!acnode.walkAble)
						return false;
					if (checkCorner(acnode))
						return false;
					node=acnode;
				}

				px=(i + 1) * nodeWidth - 1;
				if (px >= startPx && px <= endPx)
				{
					py=getPy(px);
					//trace("x2 " + px + " " + py);
					acnode=_mapsGrid.getNodeByPoint(new Point(px, py));
					if (!acnode.walkAble)
						return false;
					if (checkCorner(acnode))
						return false;
					node=acnode;
				}

			}

			//--y轴采样:
			//if (_k == 0) return true;
			acnode=s.y < e.y ? s : e;
			for (i=miny; i <= maxy; i++)
			{
				py=i * nodeHeight + 1;
				if (py >= startPy && py <= endPy)
				{
					px=getPx(py);
					//trace("y1 " + px + " " + py);
					acnode=_mapsGrid.getNodeByPoint(new Point(px, py));
					if (!acnode.walkAble)
						return false;
					if (checkCorner(acnode))
						return false;
					node=acnode;
				}

				py=(i + 1) * nodeHeight - 1;
				if (py >= startPy && py <= endPy)
				{
					px=getPx(py);
					//trace("y2 " + px + " " + py);
					acnode=_mapsGrid.getNodeByPoint(new Point(px, py));
					if (!acnode.walkAble)
						return false;
					if (checkCorner(acnode))
						return false;
					node=acnode;
				}

			}

			return true;





		}

		private function getPx(yy:Number):Number
		{

			//if (_isPanX) return _panXvalue;
			if (_isPanY)
				return _panYvalue;
			return (yy - _b) / _k;
		}

		private function getPy(xx:Number):Number
		{
			if (_isPanX)
				return _panXvalue;
			//if (_isPanY) return _panYvalue;
			return _k * xx + _b;
		}

		private function checkCorner(n:Node):Boolean
		{
			var face:int=getface(n);
			var c1:Node;
			var c2:Node;
			switch (face)
			{
				case 4:
					c1=_mapsGrid.getNodeByPoint(new Point(n.y, n.x - 1)) as Node;
					c2=_mapsGrid.getNodeByPoint(new Point(n.y - 1, n.x)) as Node;
					break;
				case -2:
					c1=_mapsGrid.getNodeByPoint(new Point(n.y, n.x - 1)) as Node;
					c2=_mapsGrid.getNodeByPoint(new Point(n.y + 1, n.x)) as Node;
					break;
				case -4:
					c1=_mapsGrid.getNodeByPoint(new Point(n.y, n.x + 1)) as Node;
					c2=_mapsGrid.getNodeByPoint(new Point(n.y + 1, n.x)) as Node;
					break;
				case 2:
					c1=_mapsGrid.getNodeByPoint(new Point(n.y, n.x + 1)) as Node;
					c2=_mapsGrid.getNodeByPoint(new Point(n.y + 1, n.x)) as Node;
					break;
				default:
					return false;
					break;
			}
			if (!c1.walkAble && !c2.walkAble)
				return true;
			return false;
		}

		private function getface(n:Node):int
		{
			var result:int=(n.y - node.y) * 3 + (n.x - node.x);
			return result;
		}

	}
}